package com.fancy.net.sock
{
	
	import com.fancy.framework.BundleManager;
	import com.fancy.framework.BundleModuleName;
	import com.fancy.framework.BundleNotice;
	import com.fancy.framework.Debug;
	import com.fancy.net.stream.EncodeBase;
	import com.fancy.net.stream.StreamDic;
	import com.fancy.ui.notice.UIKeyNotice;
	import com.fancy.ui.notice.UINoticeType;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.Socket;
	import flash.utils.ByteArray;

	public class SockBase extends EventDispatcher
	{
		protected var _socket:Socket = new Socket();
		
		protected var _ip:String = "";
		protected var _port:int = 0;
		
		protected var _isConnected:Boolean = false;
		public function get isConnected():Boolean { return _isConnected; }
		
		protected var _sendBufferArr:Array = [];
		protected var _recvBufferArr:Array = [];
		
		public function SockBase()
		{
			preConstruct();
			addEventListeners();
		}
		
		protected function preConstruct():void
		{
			
		}
		
		protected function addEventListeners():void
		{
			_socket.addEventListener(Event.CONNECT, connectHandler);
			_socket.addEventListener(ProgressEvent.SOCKET_DATA, readHandler);
			_socket.addEventListener(Event.CLOSE, closeHandler); //监听连接关闭
			_socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); //监听连接关闭  
			_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); //监听连接关闭
		}
		
		protected function connectHandler(event:Event):void
		{
			this.dispatchEvent(event);
			_isConnected = true;
		}
		
		protected function readHandler(event:ProgressEvent):void
		{
			this.dispatchEvent(event);
		}
		
		protected function closeHandler(event:Event):void
		{
			this.dispatchEvent(event);
			_isConnected = false;
		}
		
		protected function ioErrorHandler(event:IOErrorEvent):void
		{
			trace("SockBase::ioErrorHandler(event:IOErrorEvent)", event.text);
			_isConnected = false;
			var notice:BundleNotice = new BundleNotice(UINoticeType.KEY_EVENT, UIKeyNotice.SOCKET_CONNECT_ERROR);
			BundleManager.instance.getLeaderByModuleName(BundleModuleName.USER_INTERFACE).execute(notice);
		}
		
		protected function securityErrorHandler(event:SecurityErrorEvent):void
		{
			trace("SockBase::securityErrorHandler(event:SecurityErrorEvent)", event.text);
			_isConnected = false;
			var notice:BundleNotice = new BundleNotice(UINoticeType.KEY_EVENT, UIKeyNotice.SOCKET_CONNECT_ERROR);
			BundleManager.instance.getLeaderByModuleName(BundleModuleName.USER_INTERFACE).execute(notice);
		}
		
		public function exeConnect(ip:String, port:int):void
		{
			this._ip = ip;
			this._port = port;
			if(_isConnected == true)
			{
				_socket.close();
			}
			_socket.connect(_ip, _port);
		}
		
		public function exeClose():void
		{
			_socket.close();
			_isConnected = false;
		}
		
		public function exeWrite(bytes:ByteArray, isSend:Boolean=true):void
		{
			if(isSend)
			{
				if(isConnected)
				{
					var sendBytes:ByteArray = makeSendBytes(bytes);
					_socket.writeBytes(sendBytes);
					exeFlush();
				}
				else
				{
					Debug.Error("SockBase::exeWrite 想要立即发送却又没有建立连接");
				}
			}
			else
			{
				_sendBufferArr.push(bytes);
			}
		}
		
		public function exeSendBuffer():void
		{
			if(_sendBufferArr.length > 0)
			{
				while(_sendBufferArr.length > 0)
				{
					var buffer:ByteArray = _sendBufferArr.shift();
					exeWrite(buffer, false);
				}
				exeFlush();
			}
		}
		
		public function exeClearSendBuffer():void
		{
			while(_sendBufferArr.length > 0)
			{
				_sendBufferArr.pop();
			}
		}
		
		public function exeFlush():void
		{
			_socket.flush();
		}
		
		protected function makeSendBytes(bytes:ByteArray):ByteArray
		{
			var sendBytes:ByteArray = new ByteArray();
			SockUtil.writeInt(bytes.length, sendBytes);
			sendBytes.writeByte(0);//预留
			sendBytes.writeByte(0);//预留
			sendBytes.writeBytes(bytes, 0, bytes.length);
			var pleg:int = sendBytes.length;
			var pp:int = Math.floor(((pleg+7)/8))*8 - pleg;
			for(var i:int = 0; i < pp; i++)
			{
				sendBytes.writeByte(0);
			}
			return sendBytes;
		}
		
		public function sendNoticeToServer(notice:BundleNotice):void
		{
			var encoder:EncodeBase = StreamDic.getEncoder(notice.name);
			var bytes:ByteArray = encoder.getBytes(notice.body);
			if(isConnected == true)
			{
				exeWrite(bytes, true);
			}
			else
			{
				exeWrite(bytes, false);
			}
		}
		
	}
}